package simtester.test;

import static org.junit.Assert.*;

import com.gmongo.GMongo
import com.mongodb.DBRef
import geb.junit4.GebReportingTest
import groovy.time.TimeCategory
import java.text.DateFormat
import java.text.SimpleDateFormat
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import simtester.test.pages.*
import simtester.test.Utils

class RunScriptTests extends GebReportingTest {
    static def testConfig
    static def db
    def testusername = 'Linh'
    def testpw = 'pass'
    def testcaseName = 'DefaultTest'
    def testrunName = "TestRun 1"

    @BeforeClass
    static void setUpAll() {
        testConfig = new ConfigSlurper().parse(new File('grails-app/conf/SimTesterConfig.groovy').toURI().toURL())
        db = new GMongo().getDB(testConfig.test.dbname)
        Utils.dropCollections(db)
    }
    
    @AfterClass
    static void tearDownAll() {
        Utils.dropCollections(db)
    }
    
    @Before
    public void setUp() throws Exception {
        db.user << [_id: 13L, team: new DBRef(null, 'team', 12L), username: testusername, password: testpw.encodeAsMD5(), dateCreated: new Date(), lastUpdated: new Date()]
        def testScript = '''\
package simtester.agent
import geb.*
import groovyx.net.http.ContentType
class AgentScript {
  static runtest(args) {
    def log = args.logger
    def sutAddr = 'http://www.google.com/'
    def sut = new RESTCli(args, sutAddr, ContentType.HTML)
    sut.get(path: '')
  }
}'''
        db.testCase << [_id: 7L, type: 'GUI', team: new DBRef(null, 'team', 12L), name: testcaseName, owner: new DBRef(null, 'user', 13L), script: testScript, dateCreated: new Date(), lastUpdated: new Date()]
        
        def tc = db.testCase.findOne(name: testcaseName)
        db.team << [_id: 12L, name: 'svt', users: [new DBRef(null, 'user', 13L)], testcases: [new DBRef(null, 'testCase', 7L)]]
    }

    @After
    public void tearDown() throws Exception {
        db.resultEntry.remove([:])
        db.testRun.remove([:])
        db.testCase.remove([:])
        db.user.remove([:])
        db.team.remove([:])
        def dirs = new File(testConfig.test.env).listFiles()
        dirs.each {
            new AntBuilder().delete(dir: it)
        }
    }
    
    @Test
    void runDefaultTestScript() {
        to LoginPage
        assert at(LoginPage)
        auth.login(testusername, testpw)

        assert at(HomePage)
        $('a', text: 'Test Cases').click(TestRunPage)
        
        // Choose the default test and run it
        assert at(TestRunPage)
        $('#runform').testcase = db.testCase.findOne(name: testcaseName)._id
        $('#runform').runtest().jquery.click()
        
        // At the run-test wizard. Enter name, then finish
        $('#runform').trname = testrunName
        $('#wiznext').jquery.click()
        $('#wizfinish').jquery.click()
        
        assert at(RunningTestsPage)
        assert runningTestsTable.size() == 1
        assert runningTestsTable[0].testname == testrunName
        assert runningTestsTable[0].startdate =~ /^\d\d\/\d\d\/\d{4} \d\d:\d\d:\d\d$/ //$

        // Click the "View" button for this completed execution to see the test results
        runningTestsTable[0].view.click(TestResultsPage)
        
        assert at(TestResultsPage)
        assert stats.contains('Status: Running')
        assert stats.contains('Start Date:')
        assert stats.contains('End Date:')
        assert stats.contains('Total Duration:')
        assert stats.contains('Number of iterations: 1')
        
        waitFor(40, 2) { stats.contains('Status: Completed') }
        
        db.resultEntry.find().each {
            println " result: $it"
        }
        
        $('div.section').click()
        //$('#test1').jquery.click()
        waitFor(10, 2) {
            $('pre').text().contains('GET http://www.google.com/ content-type:text/html')
        }
        //waitFor(10) { $('pre').text().contains('Title: Google') }

        details.click(TestRunDetailsPage)
        
        assert at(TestRunDetailsPage)
        assert detailsTable.any {
            it.timestamp =~ /^\d\d\/\d\d\/\d{4} \d\d:\d\d:\d\d\.\d{3}$/ \
            && it.type      == 'GET' \
            && it.entry     == 'INFO: http://www.google.com/ content-type:text/html' \
            && it.response  =~ /\d+/
        }
    }
    
    @Test
    void runStats() {
        def starttime = new SimpleDateFormat('MM/dd/yyyy HH:mm:ss').parse('10/24/1984 04:30:30')
        def endtimeText = '10/26/1984 05:35:35'
        def endtime = new SimpleDateFormat('MM/dd/yyyy HH:mm:ss').parse(endtimeText)
        def tc = db.testCase.findOne(name: testcaseName)
        db.testRun << [_id: 60L, testcase: new DBRef(null, 'testCase', tc._id), status: 'completed', repeats: 2, dateCreated: starttime, lastUpdated: endtime, endDate: endtimeText]
        
        to LoginPage
        assert at(LoginPage)
        auth.login(testusername, testpw)
        
        to RunningTestsPage
        assert at(RunningTestsPage)
        assert runningTestsTable[0].status == 'completed'
        assert runningTestsTable[0].enddate == endtimeText

        def tr = db.testRun.findOne()
        
        to TestResultsPage, tr._id
        assert at(TestResultsPage)
        assert stats.contains('Total Duration: 2 days, 1 hours, 5 minutes, 5.000 seconds')
        assert stats.contains('Number of iterations: 2')
    }
    
    @Test
    void viewTestRunRequestsInDetail() {
        def tc = db.testCase.findOne(name: testcaseName)
        db.testRun << [_id: 20L,
                       testcase: new DBRef(null, 'testCase', tc._id),
                       iterations: [new DBRef(null, 'iteration', 1L)],
                       status: 'completed',
                       type: 'GUI',
                       repeats:1,
                       users: 1,
                       dateCreated: new Date(),
                       lastUpdated: new Date(),
                       endDate: new Date()]
        
        db.iteration << [_id: 1L, user: 1, num: 1, startDate: new Date(), endDate: new Date()]
        
        def entryText    = 'some log entry'
        def levelText    = 'INFO'
        def typeText     = 'PUT'
        def responseText = '380'
        def tr = db.testRun.findOne()
        db.resultEntry << [_id: 1L, testrun: new DBRef(null, 'testRun', tr._id), user: 1, iteration: 1, entry: entryText, timestamp: new Date(), level: levelText, type: typeText, response: responseText]
        
        to LoginPage
        assert at(LoginPage)
        auth.login(testusername, testpw)
        
        to TestResultsPage, tr._id
        assert at(TestResultsPage)
        waitFor(20, 2) { $('div.section').text() }
        $('div.section').click()

        details.click(TestRunDetailsPage)

        assert at(TestRunDetailsPage)
        assert detailsTable[0].timestamp =~ /^\d\d\/\d\d\/\d{4} \d\d:\d\d:\d\d\.\d{3}$/
        assert detailsTable[0].type      == typeText
        assert detailsTable[0].entry     == "$levelText: $entryText"
        assert detailsTable[0].response  == responseText
    }

}
